# -*- coding: utf-8 -*-
import json
import datetime
from rest_framework import mixins
from rest_framework import generics
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters
from rest_framework.exceptions import ParseError
# from django_excel import make_response_from_array
from rest_framework.response import Response


class QueryParameterNotPresentError(ParseError):
    """查询参数不存在且不存在默认值"""
    pass


class BaseResfulView(mixins.ListModelMixin, mixins.CreateModelMixin,
                     mixins.UpdateModelMixin, mixins.DestroyModelMixin,
                     mixins.RetrieveModelMixin, generics.GenericAPIView):
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace', 'view']
    undo_http_method_names = ['put', 'patch', 'delete', 'head', 'options', 'trace', 'view']
    done_http_method_names = ['get', 'post']
    filter_backends = (DjangoFilterBackend, filters.OrderingFilter,)
    result = {'data': []}

    def get_parameter(self, data, name, value_type, default=None, choices=None, verification=None):
        """获取查询参数"""
        value = data.get(name, default)
        if value == None:
            raise QueryParameterNotPresentError({'codemsg': "{}:必须的参数".format(name)})
        if isinstance(value, str) and len(value)==0:
            raise QueryParameterNotPresentError({'codemsg': "{}:必须的参数".format(name)})
        try:
            if value_type in ('int', int):
                value = int(value)
            elif value_type in ('str', str):
                value = str(value)
            elif value_type in ('list', list):
                if not isinstance(value, list):
                    value = json.loads(value)
                    assert isinstance(value, list)
            elif value_type in ('bool', bool):
                if isinstance(value, str):
                    if value.lower() in ['f', 'false', '0', 'null']:
                        value = False
                    else:
                        value = True
                else:
                    value = bool(value)
            elif value_type in ('datetime', datetime.datetime):
                if not type(value) == type(datetime.datetime.now()):
                    try:
                        value = datetime.datetime.strptime(value, '%Y-%m-%d %H:%M:%S')
                    except:
                        value = datetime.datetime.strptime(value, '%Y-%m-%d')
            elif callable(value_type):
                value = value_type(value)
        except Exception as e:
            raise ParseError({'codemsg': "{}:错误的类型".format(name)})

        try:
            if isinstance(choices, list):
                assert value in choices
        except:
            raise ParseError({'codemsg': "{}:错误的取值范围".format(name)})

        if verification:
            # 函数
            if callable(verification):
                if not verification(value):
                    raise ParseError({'codemsg': "{}:错误的值".format(name)})
            # 正则
            elif hasattr(verification, 'match'):
                if not verification.match(value):
                    raise ParseError({'codemsg': "{}:错误的值".format(name)})

        return value

    def get_query_parameter(self, name, value_type, default=None, choices=None, verification=None):
        """获取查询参数"""
        return self.get_parameter(self.request.query_params, name, value_type, default, choices, verification)

    def get_data_parameter(self, name, value_type, default=None, choices=None, verification=None):
        """获取data参数"""
        return self.get_parameter(self.request.data, name, value_type, default, choices, verification)

    def to_excel_data(self, config, data_list):
        """结果转excel格式数据"""
        assert 'items' in config
        items = config['items']

        excel_data = []
        excel_data.append([item['name'] for item in items])
        # print(data_list)
        for data in data_list:
            line = []
            for item in items:
                key = item.get('key', '')
                default = item.get('default')
                convert = item.get('convert', lambda x: x)

                keys = key.split('.')
                try:
                    v = None
                    for i, key in enumerate(keys):
                        if i == 0:
                            v = data[key]
                        else:
                            v = v[key]
                except:
                    v = default
                try:
                    v = convert(v)
                except:
                    v = '(异常值)'
                line.append(v)
            excel_data.append(line)
        return excel_data
